package com.shmet.tool.util;

import com.alibaba.fastjson.JSON;
import com.shmet.tool.util.handler.HandlerCompare;
import com.shmet.tool.util.handler.HandlerPushData;
import com.shmet.tool.util.handler.HandlerString;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author shmet
 * @version 1.0
 * @title: FormUtils
 * @description: 通用工具类
 * @date 2021/12/29 16:38
 */
public class FormUtils {

    /**
     * @author shmet
     * @date 2022/5/8
     * @desc 是否fastJson格式的json字符串
     */
    public static boolean isFastJsonFormat(String json) {
        try {
            if (json == null || json.length() == 0) {
                return false;
            } else {
                JSON.parse(json);
                return true;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * @author shmet
     * @date 2022/7/1
     * @desc list, add，如果为null则创建在加入
     */
    public static <T> List<T> listAppends(List<T> lists, T... ts) {
        if (lists == null) {
            lists = new ArrayList<>(Arrays.asList(ts));
        } else {
            lists.addAll(Arrays.asList(ts));
        }
        return lists;
    }

    /**
     * @author shmet
     * @date 2022/7/1
     * @desc List遍历，含判空逻辑
     * handler(T, index)
     */
    public static <T> void listForEach(List<T> lists, HandlerPushData<? super T, ? super Integer> handler) {
        if (lists != null && lists.size() > 0) {
            for (int i = 0; i < lists.size(); i++) {
                handler.handler(lists.get(i), i);
            }
        }
    }

    /**
     * 列表对象转指定泛型列表
     *
     * @param lists:   任意类型List
     * @param clazz:   返回值类型的class，如String.class
     * @param handler: 取值lamdbe表达式, 如: (data)-> data.getId()
     * @Description: 对象列表转Long列表
     * @Author: shmet
     * @Date: 2021年12月29日16:38:13
     * @return: java.util.List<java.lang.Long>
     */
    public static <T, K> List<K> listObjToList(List<T> lists, Class<K> clazz, HandlerString<? super T, ? super K> handler) {
        List<K> ids = new ArrayList<>();
        if (lists != null && lists.size() > 0) {
            for (T t : lists) {
                K k = (K) handler.handler(t);
                if (k != null) {
                    ids.add((K) handler.handler(t));
                }
            }
        }
        return ids;
    }

    /**
     * 列表对象转指定泛型列表， 变长结果集
     *
     * @param lists:   任意类型List
     * @param clazz:   返回值类型的class，如String.class
     * @param handler: 取值lamdbe表达式, 如: (data)-> data.getId()
     * @Description: 对象列表转Long列表
     * @Author: shmet
     * @Date: 2022年7月15日18:03:45
     * @return: java.util.List<java.lang.Long>
     */
    public static <T, K> List<K> listObjToListNest(List<T> lists, Class<K> clazz, HandlerString<? super T, ? super List<K>> handler) {
        List<K> ids = new ArrayList<>();
        if (lists != null && lists.size() > 0) {
            for (T t : lists) {
                List<K> listK = (List<K>) handler.handler(t);
                if (listK != null && listK.size() > 0) {
                    ids.addAll(listK);
                }
            }
        }
        return ids;
    }

    /**
     * 列表对象转指定泛型列表
     * 多一个比较，返回true才录入
     *
     * @param lists:   任意类型List
     * @param clazz:   返回值类型的class，如String.class
     * @param handler: 取值lamdbe表达式, 如: (data)-> data.getId()
     * @Description: 对象列表转Long列表
     * @Author: shmet
     * @Date: 2021年12月29日16:38:13
     * @return: java.util.List<java.lang.Long>
     */
    public static <T, K> List<K> listObjToListByCompare(List<T> lists, Class<K> clazz, HandlerString<? super T, ? super K> handler, HandlerCompare<? super T, ? super K> handlerCompare) {
        List<K> ids = new ArrayList<>();
        if (lists != null && lists.size() > 0) {
            for (T t : lists) {
                if (handlerCompare.compare(t, (K) handler.handler(t))) {
                    ids.add((K) handler.handler(t));
                }
            }
        }
        return ids;
    }

    /**
     * 列表对象转map, Key由泛型定义
     * 示例List<Object> -> Map<key, Object>
     *
     * @param lists:   任意类型List
     * @param clazz:   返回值类型的class，如: String.class
     * @param handler: 取值lamdbe表达式, 如: (data)-> data.getId()
     * @Description: list转map，k v为this
     * @Author: shmet
     * @Date: 2021年12月29日16:38:17
     * @return: java.util.List<java.lang.Long>
     */
    public static <T, K> Map<K, T> listObjToMapKey(List<T> lists, Class<K> clazz, HandlerString<? super T, ? super K> handler) {
        Map<K, T> map = new HashMap<>();
        if (lists != null && lists.size() > 0) {
            for (T t : lists) {
                map.put((K) handler.handler(t), t);
            }
        }
        return map;
    }

    /**
     * 列表对象转map, Key由泛型定义
     * 示例List<Object> -> Map<key, value>
     *
     * @author shmet
     * @date 2022/3/21
     * @desc 转注入处理map的结构中，不使用List<T>类型
     */
    public static <T, K, J> Map<K, J> listObjToMapKey(List<T> lists, Class<K> clazz, HandlerString<? super T, ? super K> handlerKey, HandlerString<? super T, ? super J> handlerValue) {
        Map<K, J> map = new HashMap<>();
        if (lists != null && lists.size() > 0) {
            for (T t : lists) {
                map.put((K) handlerKey.handler(t), (J) handlerValue.handler(t));
            }
        }
        return map;
    }

    /**
     * list对象包含某个值
     *
     * @param lists   列表
     * @param k       比较值
     * @param handler 比较器
     * @param <T>     列表泛型
     * @param <K>     比较值泛型
     * @return
     */
    public static <T, K> boolean listInclude(List<T> lists, K k, HandlerCompare<? super T, ? super K> handler) {
        if (lists != null && lists.size() > 0) {
            for (T data : lists) {
                if (handler.compare(data, k)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 根据条件过滤列表数据
     *
     * @param lists
     * @param k
     * @param handler
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> List<T> listFilter(List<T> lists, K k, HandlerCompare<? super T, ? super K> handler) {
        if (lists != null && lists.size() > 0) {
            lists.removeIf((data) -> handler.compare(data, k));
        }
        return lists;
    }

    /**
     * @author shmet
     * @date 2022/6/13
     * @desc list剔除重复值
     */
    public static <T, K> List<T> listFilterRepeat(List<T> lists, K k, HandlerString<? super T, ? super K> handlerKey) {
        List<T> newList = new ArrayList<>();
        if (lists != null && lists.size() > 0) {
            Map map = new HashMap();
            for (T t : lists) {
                if (!map.containsKey(handlerKey.handler(t))) {
                    map.put(handlerKey.handler(t), t);
                    newList.add(t);
                }
            }
        }
        return newList;
    }

    /**
     * list数据合并, 比如表单选项查询浏览数据， 按照module_type合并id，减少分次调用的消耗
     *
     * @param tLists:
     * @param clazz:
     * @param handlerKey:
     * @param pushData:
     * @Author: shmet
     * @Date: 2022/7/22 16:18
     * @return: java.util.List<T>
     */
    public static <T, K> List<T> buildListDataMarge(List<T> tLists, Class<K> clazz, HandlerString<? super T, ? super K> handlerKey, HandlerPushData<T, T> pushData) {
        if (tLists != null && tLists.size() > 0) {
            Map<K, T> valueMap = new HashMap<>(tLists.size());
            for (T t : tLists) {
                K k = (K) handlerKey.handler(t);
                if (valueMap.containsKey(k)) {
                    pushData.handler(valueMap.get(k), t);
                } else {
                    valueMap.put(k, t);
                }
            }
            tLists.clear();
            tLists.addAll(valueMap.values());
        }
        return tLists;
    }

    /**
     * 重点：仅支持set数组型的场景，特定化场景工具函数
     *
     * @param targetList: 目标数据，返回的，一般为父级list
     * @param sourceList: 来源数据，用来放到父级list中
     * @param clazz:      compare关联参数比较的类型，target和source的关联属性类型
     * @param targetKey:  目标数据关联属性key，一般为父级id
     * @param compareKey: compareKey.eq(targetKey)，来源的属性和目标的属性比较
     * @param fetchData:  取target目标数据的数据列表，用内存传递的方式，将source数据放进targetList中
     * @Description: 构造数据，列表中，按照规则放入另一个list的每一个属性,list append Objs
     * @Author: shmet
     * @Date: 2022/3/16 18:39
     * @return: java.util.List<S>
     */
    public static <T, S, K> List<T> buildListAppendObjs(List<T> targetList, List<S> sourceList, Class<K> clazz, HandlerString<? super T, ? super K> targetKey, HandlerString<? super S, ? super K> compareKey, HandlerString<? super T, ? super List<S>> fetchData) {
        if (targetList == null || targetList.size() == 0 || sourceList == null || sourceList.size() == 0) {
            return targetList;
        }
        // 进行数据包装
        Map<K, T> sourceMap = FormUtils.listObjToMapKey(targetList, clazz, targetKey);
        for (S source : sourceList) {
            if (sourceMap.containsKey(compareKey.handler(source))) {
                T target = sourceMap.get(compareKey.handler(source));
                List<S> sourceTargets = (List<S>) fetchData.handler(target);
                if (sourceTargets != null) {
                    sourceTargets.add(source);
                }
            }
        }
        return targetList;
    }

    /**
     * 重点：这个是支持set单值和setList，与特定场景的不同
     *
     * @param targetList: 目标数据，返回的，一般为父级list
     * @param sourceList: 来源数据，用来放到父级list中
     * @param clazz:      compare关联参数比较的类型，target和source的关联属性类型
     * @param targetKey:  目标数据关联属性key，一般为父级id
     * @param compareKey: compareKey.eq(targetKey)，来源的属性和目标的属性比较
     * @param pushData:   取target目标数据的数据列表，用内存传递的方式，将source数据放进targetList中
     * @Description: 构造数据，列表中，按照规则放入另一个list的每一个属性,list append Objs
     * @Author: shmet
     * @Date: 2022/3/16 18:39
     * @return: java.util.List<S>
     */
    public static <T, S, K> List<T> buildListAppendObj(List<T> targetList, List<S> sourceList, Class<K> clazz, HandlerString<? super T, ? super K> targetKey, HandlerString<? super S, ? super K> compareKey, HandlerPushData<? super T, ? super S> pushData) {
        if (targetList == null || targetList.size() == 0 || sourceList == null || sourceList.size() == 0) {
            return targetList;
        }
        // 进行数据包装
        Map<K, T> sourceMap = FormUtils.listObjToMapKey(targetList, clazz, targetKey);
        for (S source : sourceList) {
            if (sourceMap.containsKey(compareKey.handler(source))) {
                T target = sourceMap.get(compareKey.handler(source));
                // 塞数据
                pushData.handler(target, source);
            }
        }
        return targetList;
    }

    /**
     * @author shmet
     * @date 2022/6/8
     * @desc 构造数据，列表中，按照key对应的map的key值，取数据调用赋值
     */
    public static <T, K, S> List<T> buildListAppendObjByMap(List<T> dataList, Map<K, S> sourceMap, Class<K> keyClazz, HandlerString<? super T, ? super K> handlerKey, HandlerPushData<? super T, ? super S> pushData) {
        if (dataList == null || dataList.size() == 0 || sourceMap == null || sourceMap.size() == 0) {
            return dataList;
        }
        for (T t : dataList) {
            if (sourceMap.containsKey(handlerKey.handler(t))) {
                pushData.handler(t, sourceMap.get(handlerKey.handler(t)));
            }
        }
        return dataList;
    }


    /**
     * @author shmet
     * @date 2022/3/21
     * @desc list join拼接字符串
     */
    public static <T, K> String listJoinString(List<T> list, String delimiter, HandlerString<? super T, ? super K> handler) {
        if (list != null && list.size() > 0) {
            List tempList = new ArrayList();
            for (T t : list) {
                tempList.add(handler.handler(t) + "");
            }
            return String.join(delimiter, tempList);
        }
        return "";
    }


//    /**
//     * @param redis:         redis实例
//     * @param redisKey:      缓存Key
//     * @param clazz:         缓存数据的泛型
//     * @param handlerObject: 无数据的获取数据的执行器
//     * @Description: 根据Key优先从redis中根据key获取，无值则调用执行器获取保存再返回
//     * @Author: shmet
//     * @Date: 2022/6/24 16:06
//     * @return: java.util.List<T>
//     */
//    public static <T> List<T> listEntityByRedis(RedisGenericCacheManager<List<T>> redis, String redisKey, Class<T> clazz, HandlerObject<? super String, ? super List<T>> handlerObject) {
//        List<T> tList = redis.getGeneric(redisKey);
//        if (CollectionUtils.isEmpty(tList)) {
//            tList = (List<T>) handlerObject.handler(redisKey);
//            if (CollectionUtils.isNotEmpty(tList)) {
//                redis.setGeneric(redisKey, tList);
//                return tList;
//            }
//        }
//        return tList;
//    }

    /**
     * 列表合并
     *
     * @param tList:
     * @param list:
     * @Author: shmet
     * @Date: 2022/7/21 11:08
     * @return: java.util.List<T>
     */
    public static <T> List<T> listMerge(List<T> tList, List<T> list) {
        if (Objects.nonNull(tList)) {
            if (Objects.nonNull(list)) {
                tList.addAll(list);
            }
            return tList;
        }
        return list;
    }

    /**
     * map合并
     *
     * @param tMap:
     * @param kMap:
     * @Author: shmet
     * @Date: 2022/7/21 13:23
     * @return: java.util.Map<T, K>
     */
    public static <T, K> Map<T, K> mapMerge(Map<T, K> tMap, Map<T, K> kMap) {
        if (Objects.nonNull(tMap)) {
            if (Objects.nonNull(kMap)) {
                tMap.putAll(kMap);
            }
            return tMap;
        }
        return kMap;
    }

    /**
     * @author shmet
     * @date 2022/4/6
     * @desc 快速newArrayList，以便构建list使用
     */
    public static <T> List<T> newArrayList(T... a) {
        return new ArrayList<T>(Arrays.asList(a));
    }

    /**
     * @author shmet
     * @date 2022/4/6
     * @desc 快速newHashMap, 以便构建map使用
     */
    public static <T, K> FormHashMap<T, K> newHashMap() {
        return new FormHashMap();
    }

    /**
     * @author shmet
     * @date 2022/4/6
     * @desc 内部类，用来链式创建hashMap及其属性
     */
    public static class FormHashMap<T, K> {

        private Map<T, K> map;

        public FormHashMap() {
            this.map = new HashMap<>();
        }

        public FormHashMap put(T t, K k) {
            this.map.put(t, k);
            return this;
        }

        public Map<T, K> builder() {
            return this.map;
        }
    }

    /**
     * map转换成javaBeanmap转换成javaBean
     *
     * @param
     * @return
     */
    public static Object transMap2Bean(Map<String, Object> map, Object obj) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor prop : properties) {
                String key = prop.getName();
                if (map.containsKey(key) && map.get(key) != null) {
                    Object value = map.get(key);
                    Method setMethod = prop.getWriteMethod();
                    setMethod.invoke(obj, value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}
